package io.itit.ecp.admin.server.service.impl;

import cn.hutool.core.util.ObjectUtil;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import icu.mhb.mybatisplus.plugln.extend.Joins;
import io.itit.ecp.admin.common.constants.ParamConstants;
import io.itit.ecp.admin.common.enums.IMeterDeviceEnums;
import io.itit.ecp.admin.server.entity.CarbonNeutralityPlanEntity;
import io.itit.ecp.admin.server.entity.EnergyDataEntity;
import io.itit.ecp.admin.server.entity.MeterDeviceEntity;
import io.itit.ecp.admin.server.mapper.CarbonNeutralityPlanMapper;
import io.itit.ecp.admin.server.service.ICarbonNeutralityPlanService;
import io.itit.ecp.admin.server.service.ICarbonSinkDataService;
import io.itit.ecp.admin.server.service.IEnergyDataService;
import io.itit.grass.common.server.dto.ParamDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;


@Service
@RequiredArgsConstructor
public class CarbonNeutralityPlanServiceImpl extends JoinServiceImpl<CarbonNeutralityPlanMapper, CarbonNeutralityPlanEntity>
        implements ICarbonNeutralityPlanService {

    private final ICarbonSinkDataService carbonSinkDataService;

    private final IEnergyDataService energyDataService;

    @Override
    public BigDecimal queryPlanCarbonNeutrality(String sceneProjectId, LocalDate start, LocalDate end) {
        BigDecimal carbonEmissionData = ObjectUtil.defaultIfNull(queryCarbonEmissionData(sceneProjectId, start, end), BigDecimal.ZERO);
        BigDecimal carbonSinkData = queryCarbonSinkData(sceneProjectId, start, end);
        ParamDto paramDto = new ParamDto();
        paramDto.add("sceneProjectId", sceneProjectId);
        paramDto.add("solidifyDateStart", start.atTime(LocalTime.MIN).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        paramDto.add("solidifyDateEnd", start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        paramDto.add("readMeterTypeList", ParamConstants.readMeterType_zeroCarbon_list);
        BigDecimal carbonEmission = ObjectUtil.defaultIfNull(energyDataService.sum(paramDto).getCarbonEmission(), BigDecimal.ZERO);
        BigDecimal val = carbonSinkData.add(carbonEmission);
        return carbonEmissionData.subtract(val);
    }


    private BigDecimal queryCarbonEmissionData(String sceneProjectId, LocalDate start, LocalDate end) {
        LocalDateTime startTime = start.atTime(LocalTime.MIN);
        LocalDateTime endTime = end.atTime(LocalTime.MAX);
        return Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder
                        .add("SUM(carbon_emission)", "carbonEmission", false))
                .leftJoin(MeterDeviceEntity.class, MeterDeviceEntity::getId, EnergyDataEntity::getMeterDeviceId)
                .notIn(MeterDeviceEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.getZeroCarbonList())
                .end()
                .eq(EnergyDataEntity::getSceneProjectId, sceneProjectId)
                .ge(EnergyDataEntity::getSolidifyDate, startTime)
                .le(EnergyDataEntity::getSolidifyDate, endTime)
                .joinGetOne(BigDecimal.class);
    }

    private BigDecimal queryCarbonSinkData(String sceneProjectId, LocalDate start, LocalDate end) {
        return carbonSinkDataService.computeCarbonReductionTotal(sceneProjectId, start.atTime(LocalTime.MIN), end.atTime(LocalTime.MAX));
    }
}
